package com.springboot.util.common;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @description:
 * @author: zyj
 * @create: 2020-08-07 14:01
 **/
public class MyDateUtil {

    public static String dateFormatStr = "yyyy-MM-dd HH:mm:ss";
    public static String dateFormatStrShort = "yyyy-MM-dd";
    private static String dateFormatBath = "yyyyMMddHHmmssSSS";
    public static String dateFormat14 = "yyyyMMddHHmmss";

    private static final ConcurrentMap<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();

    private static final int PATTERN_CACHE_SIZE = 500;

    public static String nowDateStr(){
        return format(new Date(), dateFormatStr);
    }

    /**
     * Date转换为格式化时间
     * @param date date
     * @param pattern 格式
     * @return
     */
    public static String format(Date date, String pattern){
        return format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), pattern);
    }

    /**
     * @Description 当前时间后的时间
     * @Author zyj
     * @Date 2021/4/1 15:46
     * @param secounds 多少秒后
     * @return java.time.LocalTime
     **/
    public static Date getLocalTimeAfter(int secounds){
        LocalDateTime time = LocalDateTime.now();
        LocalDateTime newTime = time.plusSeconds(secounds);
        Date date = Date.from(newTime.atZone(ZoneId.systemDefault()).toInstant());
        return date;
    }



    /**
     * localDateTime转换为格式化时间
     * @param localDateTime localDateTime
     * @param pattern 格式
     * @return
     */
    public static String format(LocalDateTime localDateTime, String pattern){
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return localDateTime.format(formatter);
    }

    /**
     * 格式化字符串转为Date
     * @param time 格式化时间
     * @param pattern 格式
     * @return
     */
    public static Date parseDate(String time, String pattern){
        return Date.from(parseLocalDateTime(time, pattern).atZone(ZoneId.systemDefault()).toInstant());

    }

    /**
     * 格式化字符串转为LocalDateTime
     * @param time 格式化时间
     * @param pattern 格式
     * @return
     */
    public static LocalDateTime parseLocalDateTime(String time, String pattern){
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return LocalDateTime.parse(time, formatter);
    }

    /**
     * 在缓存中创建DateTimeFormatter
     * @param pattern 格式
     * @return
     */
    private static DateTimeFormatter createCacheFormatter(String pattern){
        if (pattern == null || pattern.length() == 0) {
            throw new IllegalArgumentException("Invalid pattern specification");
        }
        DateTimeFormatter formatter = FORMATTER_CACHE.get(pattern);
        if(formatter == null){
            if(FORMATTER_CACHE.size() < PATTERN_CACHE_SIZE){
                formatter = DateTimeFormatter.ofPattern(pattern);
                DateTimeFormatter oldFormatter = FORMATTER_CACHE.putIfAbsent(pattern, formatter);
                if(oldFormatter != null){
                    formatter = oldFormatter;
                }
            }
        }

        return formatter;
    }

    public static Date coverLocalDate(LocalDate localDate){
        if (localDate == null) {return null;}

        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 将java.util.Date对象转化为String字符串
     *
     * @param date      要格式的java.util.Date对象
     * @param strFormat 输出的String字符串格式的限定（如："yyyy-MM-dd HH:mm:ss"）
     * @return 表示日期的字符串
     */
    public static String dateToStr(java.util.Date date, String strFormat) {
        SimpleDateFormat sf = new SimpleDateFormat(strFormat);
        String str = sf.format(date);
        return str;
    }

    /**
     * 将String字符串转换为java.sql.Timestamp格式日期,用于数据库保存
     *
     * @param strDate    表示日期的字符串
     * @param dateFormat 传入字符串的日期表示格式（如："yyyy-MM-dd HH:mm:ss"）
     * @return java.sql.Timestamp类型日期对象（如果转换失败则返回null）
     */
    public static java.sql.Timestamp strToSqlDate(String strDate, String dateFormat) {
        SimpleDateFormat sf = new SimpleDateFormat(dateFormat);
        java.util.Date date = null;
        try {
            date = sf.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        java.sql.Timestamp dateSQL = new java.sql.Timestamp(date.getTime());
        return dateSQL;
    }

    /**
    * @Description: 格式化时间
    * @Param: []
    * @return: java.lang.String
    * @Author: zyj
    * @Date: 2020/9/11
    */
    public static String getNowDateFormat(){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormatBath);
        String dateTime = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
        return dateTime;
    }


    /**
     * @Description: 获取当天最晚时间
     * @Param: []
     * @return: java.lang.String
     * @Author: zyj
     * @Date: 2020/9/11
     */
    public static Date endOfDayTime(Date date) throws Exception{
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()),
                ZoneId.systemDefault());
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());

    }



    /**
     * @Description: 获得当天最小时间
     * @Param: []
     * @return: java.lang.String
     * @Author: zyj
     * @Date: 2020/9/11
     */
    public static Date getStartOfDay(Date date) throws Exception{
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()),
                ZoneId.systemDefault());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }



    /**
    * @Description: 校验14位时间
    * @Param: [str]
    * @return: boolean
    * @Author: zyj
    * @Date: 2020/12/15
    */
    public static boolean isValidDate14(String str){
        return isValidDate(str, dateFormat14, 14);
    }



    /**校验14位字符串是否为正确的日期格式
     *
     * @param str 日期  formatStr：日期格式   length：str日期长度
     * @return
     */
    public static boolean isValidDate(String str, String formatStr, int length) {
        if(null == str){
            return false;
        }

        boolean result = true;
        //判断字符串长度是否为8位
        if(str.length() == length){
            SimpleDateFormat format = new SimpleDateFormat(formatStr);
            try {
                // 设置lenient为false.
                // 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
                format.setLenient(false);
                format.parse(str);
            } catch (ParseException e) {
                // e.printStackTrace();
                // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
                result = false;
            }
        }else{
            result = false;
        }

        return result;
    }


}
